home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 307_01 / comx.c < prev    next >
C/C++ Source or Header  |  1990-03-18  |  25KB  |  742 lines

  1. /*
  2. HEADER:     ;
  3. TITLE:        PC com port driver;
  4. VERSION:    1.0;
  5.  
  6. DESCRIPTION:    "MS-DOS serial port device driver.  Provides buffered
  7.         input and output to serial port with optional XON/XOFF
  8.         flow control through standard read/write requests or
  9.         interrupt 0x14.
  10.  
  11.         Mixed memory model used.  COMX.C compiled as small
  12.         model with explicitly declared far pointers.  Front
  13.         end program coerces the linkage editor to produce a
  14.         tiny model executable.";
  15.  
  16. WARNINGS:    "Microsoft specific.  Startup code contained in
  17.         COMXFE.ASM does not initialize uninitialized static
  18.         variables to zero.";
  19. KEYWORDS:    Serial communications, device driver;
  20. SYSTEM:     MS-DOS v2 or later;
  21. FILENAME:    COMX.C;
  22.  
  23. SEE-ALSO:    COMX, COMXFE.ASM, COMXBE.C;
  24. AUTHORS:    Hugh Daschbach;
  25. COMPILERS:    Microsoft v5.0,v5.1;
  26. */
  27. /*----------------------------------------------------------------------*/
  28. /* comx.c: MS-DOS driver for multiple communication devices (com1 - com4).
  29.  */
  30. #include "comx.h"
  31.  
  32. /* Instalation:
  33.  * This program is installed as an MS-DOS device driver by including
  34.  * the following entry in the CONFIG.SYS file:
  35.  *        DEVICE = COMX.SYS xxx [xxx [xxx [xxx]]]
  36.  * where xxx is a com port address in hexadecimal (e.g. 3fa).  At least
  37.  * one port is required.  The driver will support as many as four.
  38.  *
  39.  * The communication devices are assumed to interrupt on either IRQ3 or
  40.  * IRQ4.  More than one device can share the same interrupt line as
  41.  * each defined port is polled on every interrupt.  Other versions of
  42.  * this driver support dedicated interrupt vectors, eliminating the
  43.  * polling operation at interrupt time.  However, even with the polling
  44.  * overhead, the driver has been tested successfully at 9600 baud on a
  45.  * 4.77 Mhz 8088.
  46.  */
  47.  
  48. /*----------------------------------------------------------------------*/
  49. /*              System Declarations                */
  50. /*----------------------------------------------------------------------*/
  51. #pragma pack(1)
  52. int inp(unsigned int);
  53. int outp(unsigned int, int);
  54. void _enable(void);
  55. void _disable(void);
  56. #pragma intrinsic(inp, outp, _enable, _disable)
  57.  
  58. /*----------------------------------------------------------------------*/
  59. /*            Local Data Declarations             */
  60. /*----------------------------------------------------------------------*/
  61. typedef unsigned char    uchar;
  62. typedef unsigned short    ushort;
  63.  
  64. /*----------------------------------------------------------------------*/
  65. /*             External Function Prototypes.            */
  66. /*----------------------------------------------------------------------*/
  67. extern void int10(unsigned ax, unsigned bx);
  68.  
  69. /*----------------------------------------------------------------------*/
  70. /*               Local function prototypes            */
  71. /*----------------------------------------------------------------------*/
  72. static    void check_block(struct comport *chan);
  73. static    int  com_int(void);
  74. static    char *define_lines(char far *cp);
  75. extern    void driver(struct rb far *rbp, int line_no);
  76. static    int  eol(int c);
  77. static    void get_char(struct comport *chan);
  78. static    void hookvect(unsigned int intnum, struct isr_block *isr,
  79.               void (cdecl *handler)());
  80. static    int  int14(ushort ax, ushort bx, ushort cx,
  81.            ushort dx, ushort ds, ushort es);
  82. static    int  isspace(int c);
  83. static    int  nop(int i);
  84. static    void put_char(struct comport *chan);
  85. static    void putc(int c);
  86. static    void puts(char *s);
  87. static    void putx(int i);
  88. static    void setspeed(struct comport *chan, int sti);
  89.  
  90. /*----------------------------------------------------------------------*/
  91. /*             Driver interface declarations            */
  92. /*----------------------------------------------------------------------*/
  93. enum opcodes {            /* Driver operation codes:        */
  94.     INIT = 0,            /* initialization            */
  95.     MEDIA_CHECK,        /* media check                */
  96.     BUILD_BPB,            /* build BIOS Parameter Block        */
  97.     INPUT_IOCTL,        /* input control string         */
  98.     INPUT,            /* read                 */
  99.     NON_DEST_INPUT,        /* non destructive input        */
  100.     INPUT_STATUS,        /* input available status        */
  101.     INPUT_FLUSH,        /* flush input buffer            */
  102.     OUTPUT,            /* write                */
  103.     OUTPUT_VERIFY,        /* write with verify            */
  104.     OUTPUT_STATUS,        /* output busy status            */
  105.     OUTPUT_FLUSH,        /* flush output buffer            */
  106.     OUTPUT_IOCTL,        /* output control string        */
  107.     DEVICE_OPEN,        /* device open (removable media)    */
  108.     DEVICE_CLOSE,        /* device close (removable media)    */
  109.     REMOVEABLE_MEDIA,        /* more removable media         */
  110.     GENERIC_IOCTL = 19,     /* more ioctl                */
  111.     GET_LOGICAL_DEVICE = 23,    /* get logical device            */
  112.     SET_LOGICAL_DEVICE = 24    /* set logical device            */
  113. };
  114.  
  115.                 /* Driver status indicators:        */
  116. #define DONE    0x0100        /* I/O done                */
  117. #define BUSY    0x0200        /* device busy                */
  118. #define ERROR    0x8000        /* I/O error                */
  119.  
  120. enum errcodes {         /* Driver error codes:            */
  121.     WRITE_PROTECT,        /* write protect violation        */
  122.     UNKNOWN_UNIT,        /* unknown unit             */
  123.     NOT_READY,            /* device non ready            */
  124.     UNKNOWN_COMMAND,        /* unknown command            */
  125.     CRC_ERROR,            /* CRC error                */
  126.     BAD_STRUCT_LENGTH,        /* bad drive request structure length    */
  127.     SEEK_ERROR,         /* seek error                */
  128.     UNKNOWN_MEDIA,        /* unknown media            */
  129.     SECTOR_NOT_FOUND,        /* sector not found            */
  130.     PAPER_OUT,            /* printer out of paper         */
  131.     WRITE_FAULT,        /* write fault                */
  132.     READ_FAULT,         /* read fault                */
  133.     GENERAL_FAILURE,        /* general failure            */
  134.     RESV_D,            /* reserved                */
  135.     RESV_E,            /* reserved                */
  136.     INVALID_DISK_CHANGE     /* invalid disk change            */
  137. };
  138.  
  139. typedef struct rb {        /* I/O Request block            */
  140.     uchar  len;         /* request block length         */
  141.     uchar  unit;        /* unit code                */
  142.     uchar  op_code;        /* operation code            */
  143.     int    status;        /* status code                */
  144.     char   resv[8];        /* reserved                */
  145.     union {
  146.     struct {
  147.         uchar    count;    /* unit count                */
  148.         char far *end;    /* end of resident module        */
  149.         char far *bpbp;    /* BPB array pointer            */
  150.         uchar    drive;    /* drive number             */
  151.     } init;
  152.     struct {
  153.         uchar    media;    /* media descriptor byte        */
  154.         char far *buf;    /* transfer buffer pointer        */
  155.         int      count;    /* byte/sector count            */
  156.         int      sector;    /* starting sector number        */
  157.         char far *vol_id;    /* volume idenitifier pointer        */
  158.     } inout;
  159.     char    ndi;        /* non destructive input data byte    */
  160.     } os;            /* operation specific            */
  161. } rb;
  162.  
  163. /*----------------------------------------------------------------------*/
  164. /*        Interrupt service routine interface declaration        */
  165. /*----------------------------------------------------------------------*/
  166. typedef struct isr_block {    /* Interrupt Service Routine        */
  167.     uchar   push_es;
  168.     uchar   push_ds;
  169.     uchar   push_dx;
  170.     uchar   push_cx;
  171.     uchar   push_bx;
  172.     uchar   push_ax;
  173.     ushort  mov_ax_cs;
  174.     ushort  mov_ds_ax;
  175.     uchar   call;
  176.     ushort  target;
  177.     ushort  or_ax_ax;
  178.     uchar   pop_ax;
  179.     uchar   pop_bx;
  180.     uchar   pop_cx;
  181.     uchar   pop_dx;
  182.     uchar   pop_ds;
  183.     uchar   pop_es;
  184.     ushort  jz_ip01;
  185.     uchar   cs_prefix;
  186.     ushort  jmp;
  187.     void    (far **fnpp)(void);
  188.     uchar   iret;
  189.     void    (far *fnp)(void);
  190. } isr_block;
  191.  
  192. /*----------------------------------------------------------------------*/
  193. /*            Hardware interface declarations            */
  194. /*----------------------------------------------------------------------*/
  195.                 /* Line Status Register definition    */
  196. #define LSR_RDA     1        /* receive data available        */
  197. #define LSR_OR        2        /* overrun error            */
  198. #define LSR_PE        4        /* parity error             */
  199. #define LSR_FE        8        /* framing error            */
  200. #define LSR_BI     0x10        /* break interupt            */
  201. #define LSR_TBA  0x20        /* transmit holding buffer available    */
  202. #define LSR_TSRE 0x40        /* transmit shift buffer empty        */
  203.  
  204.                 /* Modem Control Register definitions    */
  205. #define MCR_DTR     1        /* data terminal ready            */
  206. #define MCR_RTS     2        /* request to send            */
  207. #define MCR_OUT1    4        /* reset Hayes Smartmodem        */
  208. #define MCR_OUT2    8        /* enable Hayes Smartmodem interrupts    */
  209. #define MCR_LOOP 0x10        /* loop back test enable        */
  210.  
  211.                 /* Interrupt Identification Register    */
  212. #de